package com.kalvan.core.utils;

import com.kalvan.core.exception.BizException;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 统一时间工具类
 *
 * @author chenliang
 */
public class Sysdate {
    // 毫秒
    private static int gap = 0;
    private static final String YMDHMS = "yyyy-MM-dd HH:mm:ss";
    private static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    private static final String YMD = "yyyy-MM-dd";
    private static final String YYYYMMDD = "yyyyMMdd";
    private static final String YM = "yyyy-MM";

    /**
     * 可以每天调整一次时钟 或者每次启动时调整
     *
     * @param databaseTime databaseTime
     * @throws BizException 异常
     */
    public static void init(Date databaseTime) throws BizException {
        Date time2 = new Date();
        long ll = databaseTime.getTime() - time2.getTime();
        if (Math.abs(ll) > 1000 * 3600 * 24 * 700) {
            throw new BizException("调整的时间太大[" + databaseTime + "],超过700天");
        }

        gap = (int) ll;

    }

    /**
     * 同步时间
     *
     * @param databaseTime databaseTime
     * @throws BizException 异常
     */
    public static void initLocalTime(Date databaseTime) throws BizException {
        try {
            String time = DateFormatUtils.format(databaseTime, YYYYMMDDHHMMSS);
            // String time = DateUtil.getDateTimeStr(databaseTime, false);
            String year = time.substring(0, 4);
            String month = time.substring(4, 6);
            String day = time.substring(6, 8);
            String hours = time.substring(8, 10);
            String minutes = time.substring(10, 12);
            String seconds = time.substring(12, 14);
            String osName = System.getProperty("os.name");
            if (osName.matches("^(?i)Windows.*$")) {
                Runtime.getRuntime().exec("cmd /c date " + year + "-" + month + "-" + day);
                Runtime.getRuntime().exec("cmd /c time " + hours + ":" + minutes + ":" + seconds);
            } else
            // linux or solaris;
            {
                // date 091815302010.59 ， 9月18日 15点30分 2010年，59秒 ，
                Runtime.getRuntime().exec("date " + month + day + hours + minutes + year + "." + seconds);
            }
        } catch (Exception e) {
            throw new BizException("调整时间出现错误");
        }
    }

    /**
     * 获取当前时间
     *
     * @return Date
     */
    public static Date getDate() {
        return DateUtils.addMilliseconds(new Date(), gap);
    }

    /**
     * 获取当前日期
     *
     * @param isYYYYMMDD 是否为全字符串格式
     * @return String
     */
    public static String getDateStr(boolean isYYYYMMDD) {
        if (isYYYYMMDD) {
            return DateFormatUtils.format(getDate(), YYYYMMDD);
        } else {
            return DateFormatUtils.format(getDate(), YMD);
        }
    }

    /**
     * 获取日期
     *
     * @param date       date
     * @param isYYYYMMDD 是否为全字符串格式
     * @return String
     */
    public static String getDateStr(Date date, boolean isYYYYMMDD) {
        if (isYYYYMMDD) {
            return DateFormatUtils.format(date, YYYYMMDD);
        } else {
            return DateFormatUtils.format(date, YMD);
        }
    }

    /**
     * 获取几天后或者几天前(负数)的日期
     *
     * @param day        day
     * @param isYYYYMMDD 是否为全字符串格式
     * @return String
     */
    public static String getDateStr(int day, boolean isYYYYMMDD) {
        if (isYYYYMMDD) {
            return DateFormatUtils.format(DateUtils.addDays(getDate(), day), YYYYMMDD);
        } else {
            return DateFormatUtils.format(DateUtils.addDays(getDate(), day), YMD);
        }
    }

    /**
     * 获取几天后或者几天前(负数)的日期
     *
     * @param millions   millions
     * @param isYYYYMMDD 是否为全字符串格式
     * @return String
     */
    public static String getDateStr(long millions, boolean isYYYYMMDD) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(millions);
        if (isYYYYMMDD) {
            return DateFormatUtils.format(c.getTime(), YYYYMMDD);
        } else {
            return DateFormatUtils.format(c.getTime(), YMD);
        }
    }

    /**
     * 获取当前日期
     *
     * @return int
     */
    public static int getDateInt() {
        return Integer.parseInt(DateFormatUtils.format(getDate(), YYYYMMDD));
    }

    /**
     * 获取当前时间
     *
     * @param isYYYYMMDDHHMMSS 是否为全字符串格式
     * @return String
     */
    public static String getTimeStr(boolean isYYYYMMDDHHMMSS) {
        if (isYYYYMMDDHHMMSS) {
            return DateFormatUtils.format(getDate(), YYYYMMDDHHMMSS);
        } else {
            return DateFormatUtils.format(getDate(), YMDHMS);
        }

    }

    /**
     * 获取时间戳
     *
     * @param date             date
     * @param isYYYYMMDDHHMMSS 是否为全字符串格式
     * @return String
     */
    public static String getTimeStr(Date date, boolean isYYYYMMDDHHMMSS) {
        if (isYYYYMMDDHHMMSS) {
            return DateFormatUtils.format(date, YYYYMMDDHHMMSS);
        } else {
            return DateFormatUtils.format(date, YMDHMS);
        }

    }

    /**
     * 获取"EEE MMM dd yyyy hh:mm:ss z"
     *
     * @param dateStr          dateStr
     * @param isYYYYMMDDHHMMSS isYYYYMMDDHHMMSS
     * @return String
     * @throws Exception 异常
     */
    public static String getTimeStr(String dateStr, boolean isYYYYMMDDHHMMSS) throws Exception {
        dateStr = dateStr.replace("GMT", "").replaceAll("\\(.*\\)", "");
        return getTimeStr(DateUtils.parseDate(dateStr, Locale.ENGLISH, "EEE MMM dd yyyy hh:mm:ss z"), isYYYYMMDDHHMMSS);
    }

    /**
     * 获取几天后或者几天前(负数)的时间
     *
     * @param day              day
     * @param isYYYYMMDDHHMMSS 是否为全字符串格式
     * @return String
     */
    public static String getTimeStr(int day, boolean isYYYYMMDDHHMMSS) {
        if (isYYYYMMDDHHMMSS) {
            return DateFormatUtils.format(DateUtils.addDays(getDate(), day), YYYYMMDDHHMMSS);
        } else {
            return DateFormatUtils.format(DateUtils.addDays(getDate(), day), YMDHMS);
        }
    }

    /**
     * 获取几天后或者几天前(负数)的时间
     *
     * @param millions         millions
     * @param isYYYYMMDDHHMMSS 是否为全字符串格式
     * @return String
     */
    public static String getTimeStr(long millions, boolean isYYYYMMDDHHMMSS) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(millions);
        if (isYYYYMMDDHHMMSS) {
            return DateFormatUtils.format(c.getTime(), YYYYMMDDHHMMSS);
        } else {
            return DateFormatUtils.format(c.getTime(), YMDHMS);
        }
    }

    /**
     * 获取几天后的时间
     *
     * @param isYYYYMMDDHHMMSS 是否为全字符串格式
     * @return String
     */
    public static String getTimeStrBegin(boolean isYYYYMMDDHHMMSS) {
        if (isYYYYMMDDHHMMSS) {
            return getDateStr(true) + "000000";
        } else {
            return getDateStr(false) + " 00:00:00";
        }

    }

    /**
     * 比较两个时间之间间隔天数 YMDHMS
     *
     * @param stime stime
     * @param etime etime
     * @return long
     * @throws BizException 异常
     */
    public static long getBetweenDaysByTime(String stime, String etime) throws BizException {
        SimpleDateFormat df = new SimpleDateFormat(YMDHMS);
        Date sdate = null;
        Date eDate = null;
        try {
            sdate = df.parse(stime);
            eDate = df.parse(etime);
        } catch (ParseException e) {
            throw new BizException("解析时间出错");
        }

        long betweendays = (long) ((eDate.getTime() - sdate.getTime()) / (1000 * 60 * 60 * 24) + 0.5);// 天数间隔
        return betweendays;
    }

    /**
     * 比较两个时间之间间隔天数 YMDHMS
     *
     * @param sdate      sdate
     * @param edate      edate
     * @param isYYYYMMDD isYYYYMMDD
     * @return long
     * @throws BizException 异常
     */
    public static long getBetweenDaysByDate(String sdate, String edate, boolean isYYYYMMDD) throws BizException {
        SimpleDateFormat df;
        if (isYYYYMMDD) {
            df = new SimpleDateFormat(YYYYMMDD);
        } else {
            df = new SimpleDateFormat(YMD);
        }
        Date sDate = null;
        Date eDate = null;
        try {
            sDate = df.parse(sdate);
            eDate = df.parse(edate);
        } catch (ParseException e) {
            throw new BizException("解析时间出错");
        }
        // 天数间隔
        return ((eDate.getTime() - sDate.getTime()) / (1000 * 60 * 60 * 24));
    }

    /**
     * 获取两个日期之间的所有日期
     *
     * @param startTime  开始日期
     * @param endTime    结束日期
     * @param isYYYYMMDD isYYYYMMDD
     * @return List
     */
    public static List<String> getBetweenDays(String startTime, String endTime, boolean isYYYYMMDD) throws BizException {
        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        SimpleDateFormat df = null;
        if (isYYYYMMDD) {
            df = new SimpleDateFormat(YYYYMMDD);
        } else {
            df = new SimpleDateFormat(YMD);
        }
        Date start = null;
        Date end = null;
        try {
            start = df.parse(startTime);
            end = df.parse(endTime);
        } catch (ParseException e) {
            throw new BizException("解析时间出错");
        }

        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(start);

        Calendar tempEnd = Calendar.getInstance();
        tempEnd.setTime(end);
        tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
        while (tempStart.before(tempEnd)) {
            days.add(df.format(tempStart.getTime()));
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
        }
        return days;
    }

    /**
     * 获取两个日期之间的所有月份
     *
     * @param startMonth 开始(包含)
     * @param endMonth   结束(包含)
     * @return List
     */
    public static List<String> getBetweenMonths(String startMonth, String endMonth) throws BizException {
        // 返回的日期集合
        List<String> months = new ArrayList<String>();

        SimpleDateFormat df = new SimpleDateFormat(YM);
        Date start = null;
        Date end = null;
        try {
            start = df.parse(startMonth);
            end = df.parse(endMonth);
        } catch (ParseException e) {
            throw new BizException("解析时间出错");
        }
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(start);

        Calendar tempEnd = Calendar.getInstance();
        tempEnd.setTime(end);
        tempEnd.add(Calendar.MONTH, +1);// 月份加1(包含结束)
        while (tempStart.before(tempEnd)) {
            months.add(df.format(tempStart.getTime()));
            tempStart.add(Calendar.MONTH, 1);
        }
        return months;
    }

    /**
     * 获取当前月最后一天
     *
     * @param curDate curDate
     * @return Date
     */
    public static Date getCurMothLastDay(Date curDate) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(curDate);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return ca.getTime();
    }

    /**
     * 获取到次日0点的秒数
     *
     * @return int
     */
    public static int getSecondsNextDayStart() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        Long seconds = (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
        int ret = seconds.intValue();
        return ret;
    }

    /**
     * 获取几天后或者几天前(负数)的日期
     *
     * @param date       date
     * @param day        day
     * @param isYYYYMMDD 是否为全字符串格式
     * @return String
     */
    public static String getDateAddStr(Date date, int day, boolean isYYYYMMDD) {
        if (isYYYYMMDD) {
            return DateFormatUtils.format(DateUtils.addDays(date, day), YYYYMMDD);
        } else {
            return DateFormatUtils.format(DateUtils.addDays(date, day), YMD);
        }
    }

    /**
     * 获取几天后或者几天前(负数)的日期
     *
     * @param beginDay   beginDay
     * @param day        day
     * @param isYYYYMMDD 是否为全字符串格式
     * @return String
     */
    public static String getDateAddStr(String beginDay, int day, boolean isYYYYMMDD) {
        try {
            if (isYYYYMMDD) {
                SimpleDateFormat dateFormat = new SimpleDateFormat(YYYYMMDD);
                return DateFormatUtils.format(DateUtils.addDays(dateFormat.parse(beginDay), day), YYYYMMDD);
            } else {
                SimpleDateFormat dateFormat = new SimpleDateFormat(YMD);
                return DateFormatUtils.format(DateUtils.addDays(dateFormat.parse(beginDay), day), YMD);
            }
        } catch (ParseException e) {
            throw new BizException("解析时间出错");
        }
    }

    /**
     * 获取当前时间到当天的秒
     *
     * @return long
     */
    public static long getNowDaySecond() {
        long hour = 0;
        Date startDate = new Date();

        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23,
                59, 59);
        Date endOfDate = calendar.getTime();
        hour = (endOfDate.getTime() - startDate.getTime()) / 1000;
        return hour;
    }
}
